package com.brillilab.service.core.experiments.impl;

import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

import javax.annotation.Resource;

import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.Assert;
import org.springframework.util.CollectionUtils;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.brillilab.common.alioss.OssFileEnum;
import com.brillilab.dao.mapper.experiments.ExperimentStepMapper;
import com.brillilab.domain.enums.common.BoolEnum;
import com.brillilab.domain.enums.experiment.ExperimentStateEnum;
import com.brillilab.domain.po.experiments.Experiment;
import com.brillilab.domain.po.experiments.ExperimentPhase;
import com.brillilab.domain.po.experiments.ExperimentStep;
import com.brillilab.domain.po.system.FileManage;
import com.brillilab.domain.vo.experiments.ExperimentTipsVo;
import com.brillilab.service.core.experiments.IExperimentPhaseService;
import com.brillilab.service.core.experiments.IExperimentService;
import com.brillilab.service.core.experiments.IExperimentStepService;
import com.brillilab.service.core.system.IFileManageService;

/**
 * 实验步骤
 * 
 * @author XuZue
 * @time 2019/04/18
 */
@Service
@Transactional
public class ExperimentStepServiceImpl implements IExperimentStepService {

	@Resource
	private ExperimentStepMapper experimentStepMapper;
	@Resource
	private IExperimentService experimentService;
	@Resource
	private IExperimentPhaseService experimentPhaseService;
	@Resource
	private IFileManageService fileManageService;

	@Override
	public List<ExperimentStep> selectList(List<Long> stepIds) {
		if (stepIds != null && stepIds.size() > 0) {
			return experimentStepMapper.selectListByStepIds(stepIds);
		}
		return null;
	}

	@Override
	public void update(ExperimentStep experimentStep) {
		experimentStep.setUpdateTime(new Date());
		int i = experimentStepMapper.updateById(experimentStep);
		Assert.isTrue(i == 1, "操作失败");
	}

	@Override
	public ExperimentTipsVo selectExperimentTipsVo(Long stepId, String parentType) {
		ExperimentTipsVo experimentTipsVo = experimentStepMapper.selectExperimentTipsVo(stepId);
		if (experimentTipsVo != null) {
			List<FileManage> tipsFileList = fileManageService.selectList(OssFileEnum.TipFile, stepId);
			experimentTipsVo.setTipsFileList(tipsFileList);
		}
		return experimentTipsVo;
	}

	// **** WuMenghao ****/
	@Override
	public ExperimentStep selectById(Long stepId) {
		return experimentStepMapper.selectById(stepId);
	}

	@Override
	public ExperimentStep selectExperimentFirstStep(Long experimentId, Long phaseId) {
		return experimentStepMapper.selectOne(new LambdaQueryWrapper<ExperimentStep>()
				.eq(ExperimentStep::getExperimentId, experimentId).eq(ExperimentStep::getExperimentPhaseId, phaseId)
				.eq(ExperimentStep::getSort, 1).eq(ExperimentStep::getIsDelete, BoolEnum.FALSE.getValue()));
	}

	@Override
	public boolean updateById(ExperimentStep step) {
		step.setUpdateTime(new Date());
		return experimentStepMapper.updateById(step) > 0;
	}

	@Override
	public ExperimentStep getExperimentStepAndAssertExist(Long experimentId, Long phaseId, Long stepId, Long labId,
			Long labMemberId) {
		Experiment experiment = experimentService.selectById(experimentId);
		Assert.notNull(experiment, "实验不存在！");
		Assert.isTrue(experiment.getLabId().equals(labId), "实验不属于该实验室！");
		if (labMemberId != null) {
			Assert.isTrue(experiment.getExecutorId().equals(labMemberId), "您不是该实验的执行人，无法进行此操作！");
		}

		if(phaseId!=null){
			ExperimentPhase phase = experimentPhaseService.selectById(phaseId);
			Assert.notNull(phase, "实验阶段不存在！");
			Assert.isTrue(phase.getExperimentId().equals(experimentId), "该阶段不属于本实验！");
		}

		if(stepId!=null){

			ExperimentStep step = this.selectById(stepId);
			Assert.notNull(step, "实验步骤不存在！");
			Assert.isTrue(step.getExperimentId().equals(experimentId), "该步骤不属于本实验！");
			Assert.isTrue(step.getExperimentPhaseId().equals(phaseId), "该步骤不属于本阶段！");
			return step;
		}
		return null;
	}

	@Override
	public List<ExperimentStep> getExperimentStepList(Long experimentId) {
		return experimentStepMapper
				.selectList(new LambdaQueryWrapper<ExperimentStep>().eq(ExperimentStep::getExperimentId, experimentId)
						.eq(ExperimentStep::getIsDelete, BoolEnum.FALSE.getValue()));
	}

	@Override
	public List<ExperimentStep> getExperimentStepList(List<Long> experimentIds) {
		return experimentStepMapper
				.selectList(new LambdaQueryWrapper<ExperimentStep>().in(ExperimentStep::getExperimentId, experimentIds)
						.eq(ExperimentStep::getIsDelete, BoolEnum.FALSE.getValue()));
	}

    @Override
    public boolean deleteByExperimentId(Long experimentId) {
        return experimentStepMapper.logicallyDeleteBatchByExperimentId(experimentId) > 0;
    }

    // **** end ****//

	// **** LJ start ****//
	@Override
	public ExperimentStep insert(ExperimentStep experimentStep) {
		int insert = experimentStepMapper.insert(experimentStep);
		Assert.isTrue(insert == 1, "操作失败！");
		return experimentStep;
	}

	// **** LJ end ****//

	@Override
	public void deleteTips(Long stepId) {
		Assert.isTrue(stepId != null, "请求参数缺失！");
		int i = experimentStepMapper.deleteTips(stepId);
		Assert.isTrue(i == 1, "操作失败！");
	}

	@Override
	public void deleteById(Long stepId) {
		int i = experimentStepMapper.deleteById(stepId);
		Assert.isTrue(i == 1, "操作失败！");
	}

	@Override
	@SuppressWarnings("unchecked")
	public List<ExperimentStep> selectByPhaseId(Long phaseId) {
		return experimentStepMapper.selectList(new LambdaQueryWrapper<ExperimentStep>()
				.eq(ExperimentStep::getExperimentPhaseId, phaseId)
				.eq(ExperimentStep::getIsDelete, BoolEnum.FALSE.getValue()).orderByAsc(ExperimentStep::getSort));
	}

    @Override
    public int insertBatch(List<ExperimentStep> newSteps) {
		if(!CollectionUtils.isEmpty(newSteps)){
			return experimentStepMapper.insertBatch(newSteps);
		}
        return 0;
    }

	@Override
	public List<ExperimentStep> selectListByExperimentId(Long experimentId) {
		return experimentStepMapper.selectList(
				new LambdaQueryWrapper<ExperimentStep>()
						.eq(ExperimentStep::getExperimentId,experimentId)
						.eq(ExperimentStep::getIsDelete,BoolEnum.FALSE.getValue()));
	}

	@Override
//	@Async
	public void startStep(Long stepId) {
		ExperimentStep step = experimentStepMapper.selectById(stepId);
		if (step != null) {
			Experiment experiment = experimentService.selectById(step.getExperimentId());
			if (experiment.getState().equals(ExperimentStateEnum.NOT_STARTED.getValue())) {
				experiment.setState(ExperimentStateEnum.UNDER_WAY.getValue());
				experimentService.updateById(experiment);
			}
			
			step.setState(ExperimentStateEnum.UNDER_WAY.getValue());
			experimentStepMapper.updateById(step);

			ExperimentPhase stepPhase = experimentPhaseService.selectById(step.getExperimentPhaseId());
			Map<Long, List<ExperimentStep>> stepMap = this.getExperimentStepList(step.getExperimentId()).stream()
					.collect(Collectors.groupingBy(ExperimentStep::getExperimentPhaseId));
			List<ExperimentPhase> phaseList = experimentPhaseService.selectList(step.getExperimentId());
			if (!CollectionUtils.isEmpty(phaseList)) {
				List<Long> stepIds = new ArrayList<>();
				for (ExperimentPhase phase : phaseList) {
					List<ExperimentStep> list = stepMap.get(phase.getId());
					if (!CollectionUtils.isEmpty(list)) {
						for (ExperimentStep step2 : list) {
							if (phase.getSort() < stepPhase.getSort()) {
								if (step2.getIsDelete().equals(BoolEnum.FALSE.getValue())
										&& !step2.getState().equals(ExperimentStateEnum.COMPLETE.getValue())) {
									stepIds.add(step2.getId());
								}
							} else if (phase.getSort() == stepPhase.getSort()) {
								if (step2.getIsDelete().equals(BoolEnum.FALSE.getValue())
										&& !step2.getState().equals(ExperimentStateEnum.COMPLETE.getValue())
										&& step2.getSort() < step.getSort()) {
									stepIds.add(step2.getId());
								}
							}
						}
					}
				}

				if (!CollectionUtils.isEmpty(stepIds)) {
					ExperimentStep entity = new ExperimentStep();
					entity.setState(ExperimentStateEnum.COMPLETE.getValue());
					LambdaQueryWrapper<ExperimentStep> wrapper = new LambdaQueryWrapper<ExperimentStep>();
					wrapper.in(ExperimentStep::getId, stepIds);
					experimentStepMapper.update(entity, wrapper);
				}
			}
		}
	}

}
